/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.testis.nicmodule.core;

import org.testis.utils.DevconUtils;

import org.testis.utils.TerminalApplicationExecutor;
import org.testis.utils.WmiNetworkAdapters;
import java.io.IOException;

/**Concrete Implementor side for windows os
 *
 * @author alperb
 */
public class NetworkOSWindows extends NetworkOS {

    private WmiNetworkAdapters _wmiAdapters;

    public NetworkOSWindows() {
        _wmiAdapters = new WmiNetworkAdapters();
    }

    /**
     * enable interface parameters concrete implementation method
     * uses devcon for enabling/disabling
     * @param String iPath for interface to be enabled/disabled
     * @param boolean enabled true for up false for down
     * @return true/false to represent succes or fail
     */
    public boolean enableInterface(String iPath,
            boolean enabled) {


        if ((iPath == null) || (iPath.trim().equals(""))) {
            throw new NicModuleException(
                    NicModuleExceptionType.IFACENAMENULL,
                    "NetworkOSLinux:enableInterface called with null as interface and enabled parameter as "
                    + Boolean.toString(enabled));
        }

        String pnpId = _wmiAdapters.getPnpInstanceId(iPath);


        if (pnpId != null && !pnpId.isEmpty()) {

            boolean result = false;
            try {
                if (enabled) {
                    result = DevconUtils.enableDevice(pnpId);
                } else {
                    result = DevconUtils.disableDevice(pnpId);
                }
            } catch (IOException ex) {
                throw new NicModuleException(NicModuleExceptionType.FILEREADERR,
                        "NetworkOSWindows:enableInterface IOException error"
                        + ex.getMessage());
            } catch (InterruptedException ex) {
                throw new NicModuleException(NicModuleExceptionType.UNEXPLAINED,
                        "NetworkOSWindows:enableInterface InterruptedException error"
                        + ex.getMessage());
            }
            if (result) {
                return true;
            } else {
                throw new NicModuleException(
                        NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:enableInterface execution error...");
            }
        } else {
            throw new NicModuleException(
                    NicModuleExceptionType.NIC_NOT_FOUND,
                    "NetworkOSWindows:enableInterface network card not found. "
                    + "Possible reasons: Network card may be disabled  or not connected...");
        }
    }

    /**
     * set interface configuration parameters method
     * set configuratin by using ifconfig command
     * @param all needed parameters in String form
     * @return true/false to represent succes or fail
     */
    public boolean setInterfaceConfiguration(String iPath,
            String ip,
            String gateWay,
            String dns,
            String subnetMask,
            Boolean fromDhcp,
            String messageId) {

        try {
            if (fromDhcp) {//set to dhcp
                return setToDhcp(iPath);
            }
            if ((ip == null) || (ip.trim().equals(""))) {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:setInterfaceConfiguration called with null as interface IP:"
                        + ip + " GATEWAY:" + gateWay
                        + " DNS:" + dns
                        + " SUBNETMASK:" + subnetMask);
            }
            if ((iPath == null) || (iPath.trim().equals(""))) {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:setInterfaceConfiguration called with null as interface interface:"
                        + ip + " GATEWAY:" + gateWay
                        + " DNS:" + dns
                        + " SUBNETMASK:" + subnetMask);
            }

            StringBuffer cmd = new StringBuffer();
            cmd.append("netsh interface ip set address name=\"");
            cmd.append(iPath);
            cmd.append("\" static ");
            cmd.append(ip);

            if ((subnetMask != null) && !(subnetMask.trim().equals(""))) {
                cmd.append(" ");
                cmd.append(subnetMask);
            }

            if ((gateWay != null) && !(gateWay.trim().equals(""))) {
                cmd.append(" ");
                cmd.append(gateWay);
                cmd.append(" 1");
            }
            TerminalApplicationExecutor executor =
                    new TerminalApplicationExecutor(cmd.toString(),
                    "");
            Integer exitVal = executor.runExec();

            String outputStr = executor.getOutputString();
            String errStr = executor.getErrorString();
            if (exitVal == 0) {
                return setDns(iPath,
                        dns);

            } else {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:setInterfaceConfiguration execution error"
                        + errStr);
            }
        } catch (Exception ex) {
            throw new NicModuleException(NicModuleExceptionType.UNEXPLAINED,
                    "NetworkOSWindows:setInterfaceConfiguration exception "
                    + ex.getMessage().toString());
        }

    }

    private boolean setToDhcp(String iPath) {
        try {

            if ((iPath == null) || (iPath.trim().equals(""))) {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:setToDhcp called with null as interface:");
            }

            StringBuffer cmd = new StringBuffer();
            cmd.append("netsh interface ip set address ");
            cmd.append("\"" + iPath + "\" dhcp");
            TerminalApplicationExecutor executor =
                    new TerminalApplicationExecutor(cmd.toString(),
                    "");
            Integer exitVal = executor.runExec();

            String outputStr = executor.getOutputString();
            String errStr = executor.getErrorString();
            if (exitVal == 0) {
                return true;
            } else if (outputStr.contains(
                    "Dhcp is already enabled on this interface")) {
                return true;
            } else {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:setToDhcp execution error...outputStr:"
                        + outputStr + " Error:"
                        + errStr + " Exit code:" + exitVal);

            }
        } catch (Exception ex) {
            throw new NicModuleException(NicModuleExceptionType.UNEXPLAINED,
                    "NetworkOSWindows:setToDhcp exception "
                    + ex.getMessage().toString());
        }
    }

    /**
     * renew dhcp client method
     * uses ipconfig for renewing dhcp
     * @param interface to be renewed in String form
     * @return true/false to represent succes or fail
     */
    public boolean renewDHCPClient(String iPath) {

        try {

            if ((iPath == null) || (iPath.trim().equals(""))) {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:renewDHCPClient called with null as interface:");
            }

            StringBuffer cmd = new StringBuffer();
            cmd.append("ipconfig /release ");
            cmd.append("\"" + iPath + "\"");

            TerminalApplicationExecutor executor =
                    new TerminalApplicationExecutor(cmd.toString(),
                    "");
            Integer exitVal = executor.runExec();

            String outputStr = executor.getOutputString();
            String errStr = executor.getErrorString();
            if (exitVal == 0) {

                StringBuffer cmd2 = new StringBuffer();
                cmd2.append("ipconfig /renew ");
                cmd2.append("\"" + iPath + "\"");

                TerminalApplicationExecutor executor2 =
                        new TerminalApplicationExecutor(cmd2.toString(),
                        "");
                exitVal = executor2.runExec();
                outputStr = executor.getOutputString();
                errStr = executor.getErrorString();

                if (exitVal == 0) {
                    return true;
                } else {
                    throw new NicModuleException(
                            NicModuleExceptionType.EXECUTIONERR,
                            "NetworkOSWindows:renewDHCPClient execution error on ipconfig /renew part"
                            + errStr);
                }
            } else {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:renewDHCPClient execution error on ipconfig /release part"
                        + errStr);
            }
        } catch (Exception ex) {
            throw new NicModuleException(NicModuleExceptionType.UNEXPLAINED,
                    "NetworkOSWindows:renewDHCPClient exception "
                    + ex.getMessage().toString());
        }

    }

    /**
     * set dns private method
     * sets dns by the us of netsh command
     * @param interface to be renewed in String form
     * @return true/false to represent succes or fail
     */
    private boolean setDns(String iPath,
            String dns) {

        try {

            boolean isGetFromDhcp = false;

            if (iPath == null) {
                return false;
            }

            if (dns == null || dns.equals("")) {
                isGetFromDhcp = true;
            }

            StringBuffer cmd = new StringBuffer();
            cmd.append("netsh interface ip set dns \"");
            cmd.append(iPath);
            cmd.append("\" ");

            if (isGetFromDhcp) {
                cmd.append(" source=dhcp ");
            } else {
                cmd.append(" static  ");
                cmd.append(dns);
                cmd.append(" primary ");
            }
            TerminalApplicationExecutor executor =
                    new TerminalApplicationExecutor(cmd.toString(),
                    "");
            Integer exitVal = executor.runExec();

            String outputStr = executor.getOutputString();
            String errStr = executor.getErrorString();
            if (exitVal == 0) {
                return true;
            } else {
                throw new NicModuleException(NicModuleExceptionType.EXECUTIONERR,
                        "NetworkOSWindows:setDns execution error "
                        + errStr);
            }
        } catch (Exception ex) {
            throw new NicModuleException(NicModuleExceptionType.UNEXPLAINED,
                    "NetworkOSWindows:setDns exception "
                    + ex.getMessage().toString());
        }


    }

    public String getIp(
            String iPath) {
        String adapterIndex = _wmiAdapters.getAdapterIndexByName(iPath);
        if (adapterIndex.isEmpty()) {
            return "";
        }
        return _wmiAdapters.getNetworkAdapterIpByIndex(adapterIndex);
    }

    public String getDns(
            String iPath) {
        String adapterIndex = _wmiAdapters.getAdapterIndexByName(iPath);
        if (adapterIndex.isEmpty()) {
            return "";
        }
        return _wmiAdapters.getNetworkAdapterDnsByIndex(adapterIndex);
    }

    public String getGateway(
            String iPath) {
        String adapterIndex = _wmiAdapters.getAdapterIndexByName(iPath);
        if (adapterIndex.isEmpty()) {
            return "";
        }
        return _wmiAdapters.getNetworkAdapterGateWayByIndex(adapterIndex);
    }

    public String getSubnetMask(
            String iPath) {
       String adapterIndex = _wmiAdapters.getAdapterIndexByName(iPath);
        if (adapterIndex.isEmpty()) {
            return "";
        }
        return _wmiAdapters.getNetworkAdapterSubnetByIndex(adapterIndex);
    }

    public String getMacAddress(
            String iPath) {
        String adapterIndex = _wmiAdapters.getAdapterIndexByName(iPath);
        if (adapterIndex.isEmpty()) {
            return "";
        }
        return _wmiAdapters.getNetworkAdapterMacAddressByIndex(adapterIndex);
    }

    public boolean isEnabled(String iPath) {
        try {
            String pnpId = _wmiAdapters.getPnpInstanceId(iPath);
            if (pnpId != null && !pnpId.isEmpty()) {
                return !DevconUtils.isDeviceDisabled(pnpId);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean isInterfaceExists(String iPath) {
        return _wmiAdapters.isNetworkAdapterExists(iPath);
    }
}
